var AudioManager = require('geoAudioManager');
var AudioType = AudioManager.AudioType;
var SequenceRunner = require('geoSequenceRunner');

/**
 * 播放音频
 */
var AudioPlayer = cc.Class({
    extends: cc.Component,

    properties: {
        delay: {
            default: 0,
            type: cc.Float,
            tooltip: '延时播放语音时间'
        },
        audioClip: {
            default: null,
            type: cc.AudioClip,
            tooltip: '单个音频(先于音频数组中的音频播放，可留空)'
        },
        audioClipArray: {
            default: [],
            type: [cc.AudioClip],
            tooltip: '音频数组(后于单个音频播放，可留空)'
        },
        audioType: {
            default: AudioType.MUSIC,
            type: cc.Enum(AudioType),
        },
        // loop: false,
        numLoops:{
            default: 1,
            tooltip:'播放次数（若小于1则无限循环播放）'
        },
        multiplay: false,
        volumn: {
            default: 1,
            type: cc.Float,
        },
        completeEvents: {
            default: [],
            type: [cc.Component.EventHandler],
            tooltip: '音频播放完毕时调用，仅限于非无限循环时'
        },
        button: {
            default: null,
            type: cc.Button,
            tooltip: '触发声音时用的按钮，在非多重播放模式下，播放音频时会被禁用'
        },
        solo: {
            default: false,
            tooltip: '是否播放该音频时，其它音频都禁止响应'
        },
        playOnLoad: false,
    },
    onLoad() {
        if (this.playOnLoad === true) {
            this.play();
        }
        // 构建一个伪事件
        this._fakeEventName = "geo-audio-player-play";
    },
    onDisable() {
        // 禁用solo
        if (this.solo == true && this._isPlaying == true)
            this._setSolo(false);
    },
    onDestroy() {
        // 移除监听
        this._removeOnComplete();
    },
    /**
     * @param {function} complete, 可通过代码注入结束回调。
     */
    play(eventOrComplete) {
        if (this.multiplay === false && this._isPlaying === true) {
            return;
        }
        //
        var complete = (eventOrComplete instanceof Function) ? eventOrComplete : null;
        var event = (eventOrComplete instanceof cc.Event) ? eventOrComplete : null;

        // 避免单独调用play的事件重新播放音频
        if (event && event.type == this._fakeEventName)
            return;
        // 校正延时
        var delay = (this.delay < 0) ? 0 : this.delay;
        //
        this._isPlaying = true;
        // 构造要正式播放的音频数组
        var audioClipsToPlay = [];
        this.audioClip && audioClipsToPlay.push(this.audioClip);
        this.audioClipArray.length && (audioClipsToPlay = audioClipsToPlay.concat(this.audioClipArray));
        // 根据播放次数倍加音频数组
        var t = audioClipsToPlay;
        for (var n = 1; n < this.numLoops; ++n)
            audioClipsToPlay = audioClipsToPlay.concat(t);
        // 构造序列执行器
        this._sqRunner = new SequenceRunner();
        var sq = this._sqRunner;
        var funcs = [];
        // 加入延时
        if (delay > 0) {
            funcs.push(
                this.scheduleOnce.bind(this, sq.next.bind(sq), delay)
            );
        }
        // 播放所有音频
        audioClipsToPlay.forEach((ac => {
            funcs.push((() => {
                if (ac == null) return;
                this._removeOnComplete();
                this._audioID = AudioManager.Singleton.play(this.audioType, ac, 1, this.volumn, sq.next.bind(sq));
            }).bind(this))
        }).bind(this));
        // 播放结束回调
        funcs.push(
            this._onComplete.bind(this, complete)
        );
        //
        sq.run(funcs);

        // 非多重播放时，防止按钮被点击
        if (this.multiplay === false)
            this.button && (this.button.interactable = false);


        // solo: 开启solo
        if (this.solo === true)
            this._setSolo(true);

        // 是否发送事件
        if (event == null && this.button) {
            event = new cc.Event.EventCustom(this._fakeEventName);
            event.target = this.button.node;
            cc.Component.EventHandler.emitEvents(this.button.clickEvents, event);
        }
    },
    /**
     * 
     * @param {function} extraComplete, 额外的结束回调。 
     */
    _onComplete(extraComplete) {
        if (this.node == null || this.node.valid == false)
            return;
        this._isPlaying = false;
        // 让按钮恢复可点击
        this.button && (this.button.interactable = true);
        var e = new cc.Event.EventCustom('audioComplete');
        e.target = this.node;
        e.targetCom = this;
        cc.Component.EventHandler.emitEvents(this.completeEvents, e);
        // 调用额外结束回调
        ('function' == typeof extraComplete) && extraComplete();
        // 一次性回调, TODO: 弃用下面的用法
        this.completeHandlerOnce && this.completeHandlerOnce();
        this.completeHandlerOnce = null;
        // 持续回调, TODO: 弃用下面的用法
        this.completeHandler && this.completeHandler();
        //
        this._removeOnComplete();
        // solo: 关闭solo
        if (this.solo === true)
            this._setSolo(false);
    },
    _removeOnComplete() {
        if (this._audioID != null) {
            // 移除已有的监听
            AudioManager.Singleton.clearFinishCallback(this._audioID);
            // 禁用下面语句，可以让音频在该节点被销毁后继续播放完毕
            // AudioManager.Singleton.stopAudio(this._audioID);
        }
        this._audioID = null;
    },
    /**
     * 启用或禁用solo
     * @param {bool} bSolo 
     */
    _setSolo(bSolo) {
        // 对场景中所有的audioPlayer禁用，除了当前这个
        cc.director.getScene().getComponentsInChildren(AudioPlayer).forEach((ap) => {
            if (ap.node.isValid == true && ap !== this && ap.button != null && ap.solo == true)
                ap.button.interactable = !bSolo;
        }, this);
    }
});
